package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"

	"gitee.com/StarCitizen_CN/l10n_maker/internal/respacker"
	"gitee.com/StarCitizen_CN/stargox/pkg/logger"
)

const (
	diffTargetDir = "diff_target"
	// l10nApp 所需的一些文件，如 logo 与配置文件
	patchFiles = "patchFiles"
	outputDir  = ".\\output"
)

var (
	inputArgs    InputArgs
	inputMapData map[string]map[string]*respacker.L10nFileInfo
)

// 定义输入的目录
type InputArgs struct {
	Dirs []string `json:"dirs"`
}

func main() {

	defer func() {
		if e := recover(); e != nil {
			if err, ok := e.(error); ok {
				logger.Err(err)
				time.Sleep(time.Minute * 90)
			}
		}
	}()

	data, err := os.ReadFile("differ_input_args.json")
	if err != nil {
		if os.IsNotExist(err) {
			data, _ := json.Marshal(inputArgs)
			os.WriteFile("differ_input_args.json", data, os.ModeAppend)
		} else {
			log.Panic(err)
		}
	}
	if err := json.Unmarshal(data, &inputArgs); err != nil {
		log.Panic(err)
	}
	if err := os.RemoveAll(outputDir); err != nil {
		log.Panic(err)
	}

	if err := logger.Setup(
		logger.SetOutput(outputDir+"\\log\\diffchecker", false),
		logger.SetDebugMode(true),
	); err != nil {
		logger.ShowGuiMsg("初始化日志工具异常", err.Error())
		os.Exit(1)
	}

	defer func() {
		logger.Var("执行完毕")
		time.Sleep(time.Minute * 90)
	}()

	fmt.Print("回车开始输出差分补丁")
	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')

	inputMapData = make(map[string]map[string]*respacker.L10nFileInfo)

	for _, dirName := range inputArgs.Dirs {
		dirData, err := respacker.Scan(dirName)
		if err != nil {
			log.Fatalln(err)
		}

		// 旧版本的文件数据不再需要了
		// for _, v := range dirData {
		// 	v.Data = nil
		// }

		fmt.Println(dirData)

		inputMapData[dirName] = dirData
	}

	targetMap, err := respacker.Scan(diffTargetDir)
	if err != nil {
		log.Fatalln(err)
	}

	patchFilesMap, err := respacker.Scan(patchFiles)
	if err != nil {
		log.Fatalln(err)
	}
	logger.Var("扫描完成")

	{
		logger.Var("\n\n===================================重名测试===================================")
		repeatFileMap := make(map[string][]*respacker.L10nFileInfo)

		for _, fInfo := range targetMap {
			name := filepath.Base(fInfo.RelPath)
			repeatFileMap[name] = append(repeatFileMap[name], fInfo)
		}

		for _, rf := range repeatFileMap {
			if len(rf) <= 1 {
				continue
			}
			for _, f := range rf {
				fmt.Printf("%s %s %s\n", f.Name, f.RelPath, f.Md5)
			}
		}

		for k, v := range repeatFileMap {
			if len(v) <= 1 {
				delete(repeatFileMap, k)
			}
		}

		fmt.Printf("发现%d个文件重名\n\n", len(repeatFileMap))
		logger.Var("===================================重名测试===================================\n\n")
	}

	// 投放结果
	// k: md5, v: fi
	shareMap := make(map[string]*respacker.L10nFileInfo)
	addedMap := make(map[string]*respacker.L10nFileInfo)
	changedMap := make(map[string]*respacker.L10nFileInfo)
	pathReleaseMap := make(map[string]*respacker.L10nFileInfo)

	// log
	var changedLog string
	var addedLog string
	var removedLog string

	var delList string

	// 🤮
	// dirName/fileInfo
	processedKeyMap := make(map[string]map[string]*respacker.L10nFileInfo)

	// 对比差异&合并差异文件
	var count int
	for tRelPath, tInfo := range targetMap {

		count++

		for dirName, dirData := range inputMapData {

			fmt.Printf("\r (%d/%d) %s %s", count, len(targetMap), dirName, tRelPath)

			fInfo := dirData[tRelPath]
			if fInfo == nil {
				addedMap[tRelPath] = tInfo
				addedLog += fmt.Sprintf("+ %s\n", tRelPath)
				continue
			}

			// diff 循环后 dirData 剩下的就是需要移除的文件
			delete(dirData, tRelPath)

			if tInfo.Md5 != fInfo.Md5 {
				changedMap[tRelPath] = tInfo
				changedLog += fmt.Sprintf("≠ %s: %s\n", dirName, tRelPath)
				continue
			}

			shareMap[tRelPath] = tInfo
		}

	}

	for k, v := range processedKeyMap {
		delete(v, k)
	}

	// 处理剩下的文件
	delMap := make(map[string]int)
	for dirName, dirData := range inputMapData {
		for rp, f := range dirData {
			removedLog += fmt.Sprintf("- %s: %s\n", dirName, rp)
			delMap[f.RelPath+"\n"] = 0
		}
	}

	for k := range delMap {
		delList += k
	}

	for k, v := range changedMap {
		pathReleaseMap[k] = v
	}
	for k, v := range addedMap {
		pathReleaseMap[k] = v
	}

	respacker.Write(filepath.Join(outputDir, "share"), []map[string]*respacker.L10nFileInfo{shareMap})
	respacker.Write(filepath.Join(outputDir, "new"), []map[string]*respacker.L10nFileInfo{addedMap})
	respacker.Write(filepath.Join(outputDir, "diff"), []map[string]*respacker.L10nFileInfo{changedMap})

	respacker.Write(filepath.Join(outputDir, "patch"), []map[string]*respacker.L10nFileInfo{pathReleaseMap, patchFilesMap})
	os.WriteFile(filepath.Join(outputDir, "dellist.txt"), []byte(delList), os.ModeAppend)

	fmt.Println(changedLog)
	fmt.Println(addedLog)
	fmt.Println(removedLog)

	fmt.Println("\ndiff 完成")

}
